import { ChangeDetectionStrategy, Component, Injector } from '@angular/core';
import { SFSchema } from '@delon/form';
import { ArrayService } from '@delon/util';
import { BaseOfSystemComponent } from '@routes/system/_base';
import { DeptVO } from '@types';

import { SystemDictService } from '../../dict/dict.service';
import { SystemDeptService } from '../dept.service';
import { SystemEditDeptComponent } from '../edit-dept/edit-dept.component';

export interface TreeNodeInterface extends DeptVO {
    key: string;
    perms: string;
    level?: number;
    expand?: boolean;
    children: TreeNodeInterface[];
    parent: TreeNodeInterface;
}

@Component({
    selector: 'app-system-dept-tree',
    templateUrl: './dept-tree.component.html',
    styleUrls: ['./dept-tree.component.less'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class SystemDeptTreeComponent extends BaseOfSystemComponent {
    searchSchema: SFSchema = {
        properties: {
            deptName: {
                title: '部门名称',
                type: 'string',
                ui: {
                    placeholder: '请输入部门名称'
                }
            },
            status: {
                title: '状态',
                type: 'string',
                ui: {
                    placeholder: '请选择状态',
                    widget: 'select',
                    asyncData: () => this.injector.get(SystemDictService).getDicts('sys_normal_disable')
                }
            }
        }
    };

    params: any = {};

    tableTreeExpand: boolean = false;

    listOfMapData: TreeNodeInterface[] = [];
    mapOfExpandedData: { [key: string]: TreeNodeInterface[] } = {};

    collapse(array: TreeNodeInterface[], data: TreeNodeInterface, $event: boolean): void {
        if (!$event) {
            if (data.children) {
                data.children.forEach(d => {
                    const target = array.find(a => a.key === d.key)!;
                    target.expand = false;
                    this.collapse(array, target, false);
                });
            } else {
                return;
            }
        }
    }

    convertTreeToList(root: TreeNodeInterface): TreeNodeInterface[] {
        const stack: TreeNodeInterface[] = [];
        const array: TreeNodeInterface[] = [];
        const hashMap = {};
        stack.push({ ...root, level: 0, expand: this.tableTreeExpand });

        while (stack.length !== 0) {
            const node = stack.pop()!;
            this.visitNode(node, hashMap, array);
            if (node.children) {
                for (let i = node.children.length - 1; i >= 0; i--) {
                    stack.push({ ...node.children[i], level: node.level! + 1, expand: this.tableTreeExpand, parent: node });
                }
            }
        }

        return array;
    }

    visitNode(node: TreeNodeInterface, hashMap: { [key: string]: boolean }, array: TreeNodeInterface[]): void {
        if (!hashMap[node.key]) {
            hashMap[node.key] = true;
            array.push(node);
        }
    }

    constructor(
        protected override injector: Injector,
        protected deptSrv: SystemDeptService,
        protected arrSrv: ArrayService
    ) {
        super(injector);
    }

    override ngOnInit(): void {
        this.listDept();
    }

    expandTableAll() {
        this.tableTreeExpand = !this.tableTreeExpand;
        this.listOfMapData.forEach(item => {
            this.mapOfExpandedData[item.key] = this.convertTreeToList(item);
        });
        this.cdRef.detectChanges();
    }

    listDept(params: any = {}) {
        this.deptSrv.listDept(params).subscribe(res => {
            this.listOfMapData = this.arrSrv.arrToTree<TreeNodeInterface>((res.data ?? []) as TreeNodeInterface[], {
                idMapName: 'deptId',
                parentIdMapName: 'parentId',
                cb: (item: any) => {
                    item.key = item.deptId;
                }
            });
            this.listOfMapData.forEach(item => {
                this.mapOfExpandedData[item.key] = this.convertTreeToList(item);
            });
            this.cdRef.detectChanges();
        });
    }

    searchDataGet(params: any) {
        this.listDept(params);
    }
    reSetDataGet(params: any) {
        this.listDept();
    }

    addDept() {
        this.modal
            .creatStaticModal(SystemEditDeptComponent, { item: {} }, 'lg', {
                nzTitle: '添加部门'
            })
            .subscribe(res => {
                if (res) {
                    this.listDept();
                }
            });
    }

    editDept(item: DeptVO) {
        this.modal
            .creatStaticModal(SystemEditDeptComponent, { item: item }, 'lg', {
                nzTitle: '编辑部门'
            })
            .subscribe(res => {
                if (res) {
                    this.listDept();
                }
            });
    }

    addSubDept(item: DeptVO) {
        this.modal
            .creatStaticModal(SystemEditDeptComponent, { item: { parentId: item.deptId } }, 'lg', {
                nzTitle: '编辑部门'
            })
            .subscribe(res => {
                if (res) {
                    this.listDept();
                }
            });
    }

    delDept(item: DeptVO) {
        this.modalSrv.confirm({
            nzTitle: '删除提示',
            nzContent: `是否确认删除名称为 ${item.deptName} 的数据项？`,
            nzOnOk: () =>
                this.deptSrv.delDept(item.deptId.toString()).subscribe(res => {
                    if (res.isComplete) {
                        this.msg.success('删除成功');
                    }
                    this.listDept();
                })
        });
    }
}
